Skip to main content

全局中间件之 CheckForMaintenanceMode

简介

上一章,我们看了 Pipeline 管道操作如何实现请求穿透中间件。从本章开始,我们将逐一介绍 Laravel 五大全局中间件对请求做了什么。。

做了什么:首先,应该要弄清如何做的,上一章我有提到过,就是以请求和洋葱作为参数,执行中间件的 handle 方法。

先看一下五大中间件有哪些

protected $middleware = [
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
];

这一章,我们看一下第一个中间 App\Http\Middleware\CheckForMaintenanceMode

关于 App\Http\Middleware\CheckForMaintenanceMode

从字面意思不难看出,这个中间件是检测我们整个项目有没有处于 维护模式

  • 关于维护模式,下面是一段官方文档的说明:

    https://learnku.com/docs/laravel/5.6/configuration/1353#972c4c

  • 开启维护模式

    php artisan down

    这条命令做了什么呢?

    这个要看 Illuminate\Foundation\Console\DownCommand,此类就是 php artisan down 所要运行的命令类

    <?php

    namespace Illuminate\Foundation\Console;

    use Illuminate\Console\Command;
    use Illuminate\Support\InteractsWithTime;

    class DownCommand extends Command
    {
    use InteractsWithTime;

    /**
    * 命令签名:就是执行 php artisan down 后面加的命令参数
    */
    protected $signature = 'down {--message= : The message for the maintenance mode. }
    {--retry= : The number of seconds after which the request may be retried.}
    {--allow=* : IP or networks allowed to access the application while in maintenance mode.}';

    /**
    * down 命令的描述
    *
    * Put the application into maintenance mode : 意思是开启 Laravel 应用的维护模式
    */
    protected $description = 'Put the application into maintenance mode';

    /**
    * 这个就是执行 php artisan down 命令实际运行的逻辑代码
    */
    public function handle()
    {
    // 在 storage/framework/ 目录下写入 down 文件,格式是 getDownFilePayload 方法的返回。
    file_put_contents(
    storage_path('framework/down'),
    json_encode($this->getDownFilePayload(), JSON_PRETTY_PRINT)
    );

    // 在屏幕打印成功的消息
    $this->comment('Application is now in maintenance mode.');
    }

    /**
    * down 文件的内容格式
    */
    protected function getDownFilePayload()
    {
    return [
    'time' => $this->currentTime(),
    'message' => $this->option('message'),
    'retry' => $this->getRetryTime(),
    'allowed' => $this->option('allow'),
    ];
    }

    /**
    * 获取浏览器刷新前应该等待的秒数。
    */
    protected function getRetryTime()
    {
    $retry = $this->option('retry');

    return is_numeric($retry) && $retry > 0 ? (int) $retry : null;
    }
    }

    通过 down 命令的源码我们不难看出,它的作用无非就是在 storage/framework/ 目录下创建叫 down 文件,里面的内容有:

    • time 开启维护的时间
    • message 页面的提示信息
    • retry 浏览器每隔多长时间刷新一次
    • allowed 允许进入应用的 IP 地址组

    说百遍,道万千,不如一张图----->

    file

  • 关闭维护模式

    php artisan up

    简单,不就是删掉 down 文件吗。。。这个源码不需要看了吧,不需要看了吧,不回答,就是默认喽。。好,那就不看了。。

那么,我们开启维护模式了,Laravel 又是如何知道呢(好能噢~~~~

这个就是 App\Http\Middleware\CheckForMaintenanceMode 中间件的作用了,它会知道我们到底有没有开维护模式。(好能噢~~~~

看源码:

<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;

class CheckForMaintenanceMode extends Middleware
{
/**
* 这里是定义 路由除外,意思是除了这些路由正常进入应用,其它路由过来甩它一脸。
*
* @var array
*/
protected $except = [
//
];
}

咦? handle 方法呢。。哦,原来这是子类,那肯定是在父类了,不废话了直接上父类的 handle 方法

public function handle($request, Closure $next)
{
// if 就是看有没有 down 文件;有则执行 if 里面的代码
if ($this->app->isDownForMaintenance()) {

// 将 down 文件里面的json数据转换成数组
$data = json_decode(file_get_contents($this->app->storagePath().'/framework/down'), true);

// 看一下数组里面的 allowed 与请求过来的 IP 匹配吗,匹配就进入应用
if (isset($data['allowed']) && IpUtils::checkIp($request->ip(), (array) $data['allowed'])) {
return $next($request);
}

// 这个就是看一下子类定义的除外路由,有没有与请求的路由匹配上,匹配上就进入应用
if ($this->inExceptArray($request)) {
return $next($request);
}

// 经过披荆斩棘,一路坎坷,没有一个符合条件,不好意思,甩你一脸狗粮(维护页面),难受不。。。哈哈哈
throw new MaintenanceModeException($data['time'], $data['retry'], $data['message']);
}

return $next($request);
}

代码里面说的很明白了,,再深了的内容,比如如何判断有米有 down 文件,就请各位小伙伴,自己走进去一探究竟了哈,我这里就不看了。